package com.szholly.pro.watergas_server.common.util;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.szholly.data.general.RowBase;
import com.szholly.pro.watergas_server.common.cache.RedisEhcacheUtil;
import com.szholly.pro.watergas_server.common.data.DataUtil;
import com.szholly.pro.watergas_server.common.data.DbManager;
import lrq.data.DataTable;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;

public class RedisHelper {
	
	private static RedisHelper _instance;
	
	private RedisHelper(){
		
	}
	
	public static RedisHelper getInstance(){
		if(_instance == null){
			_instance = new RedisHelper();
		}
		return _instance;
	}
	
	/**
	 * 加载字典
	 * gislin
	 * 2016年4月22日
	 * @param dictName
	 */
	public void loadDict(String dictName){
		dictName = dictName.toUpperCase();
		String keyPrix = "sysDict:"+dictName;
		
		 if(RedisDbExecute.getString(keyPrix+":init") != null){
			 return;
		 }
		
		String sql = "  SELECT dd.s_domaincode,dd.s_domaincaption，dd.S_UNIT FROM DATA_DEFULATDOMAIN DD WHERE DD.S_DOMAINNAME = '"+dictName+"' ";
		
		List<RowBase> rows = DataUtil.getSelectRows(sql, null);
		RedisDbExecute.deleteKeys(keyPrix);
		
		for(RowBase row : rows){
			String key = row.getSafeString("S_DOMAINCODE");
			String name = row.getSafeString("S_DOMAINCAPTION");
			String unit = row.getSafeString("S_UNIT");
			RedisDbExecute.setString(keyPrix+":"+key,name);
			RedisDbExecute.setString(keyPrix+":"+key+":unit",unit);
		}
		
		RedisDbExecute.setString(keyPrix+":init","true");
	}
	
	/**
	 * 翻译字典
	 * gislin
	 * 2016年4月22日
	 * @param dictName
	 * @param code
	 * @return
	 */
	public String translationDictValue(String dictName,String code){
		dictName = dictName.toUpperCase();
		String keyPrix = "sysDict:"+dictName;
		
		 if(RedisDbExecute.getString(keyPrix+":init") == null){
			 loadDict(dictName);
		 }
		 
		 String result = RedisDbExecute.getString(keyPrix+":"+code);
		 return result;
	}
	
	/**
	 * 翻译字典单位
	 * gislin
	 * 2016年4月22日
	 * @param dictName
	 * @param code
	 * @return
	 */
	public String translationDictUnit(String dictName,String code){
		dictName = dictName.toUpperCase();
		String keyPrix = "sysDict:"+dictName;
		
		 if(RedisDbExecute.getString(keyPrix+":init") == null){
			 loadDict(dictName);
		 }
		 
		 String result = RedisDbExecute.getString(keyPrix+":"+code+":unit");
		 return result;
	}
	
	/**
	 * 获取设备品牌code
	 * gislin
	 * 2016年4月25日
	 * @param pollCode
	 * @param attr
	 * @return
	 */
	public String getDeviceBandCode(String mn,String deviceCode){
		String key = "stationInfo:"+mn+":deviceInfo:"+deviceCode+"_BAND";
		String value = RedisDbExecute.getString(key);
		if(value == null){
			return "";
		}
		value = value.replace(".0", "");
		return value;
	}
	
	/**
	 * 获取站点状态 0正常、1超标、2异常、3故障
	 * gislin
	 * 2016年6月12日
	 * @param mn
	 * @return
	 */
	public String getStationStatus(String mn){
		String key = "stationInfo:"+mn+":stationStatus";
		String value = RedisDbExecute.getString(key);
		return value;
	}
	
	/**
	 * 批量获取站点状态
	 * @param mns
	 * @return
	 */
	public HashMap<String, String> getStationStatus(List<String> mns){
		Jedis jedis = RedisDbExecute.getStationStatusDB();
		Pipeline pipeLine = jedis.pipelined();
		Map<String, Response<String>> responseMap = new HashMap<>();
		
		for(String mn : mns){
			String key =  "stationInfo:"+mn+":stationStatus";
			responseMap.put(mn, pipeLine.get(key));
		}
		pipeLine.sync();
		
		HashMap<String, String> result = new HashMap<>();
		
		for(String mn : mns){
			String value = responseMap.get(mn).get();
			result.put(mn, value);
		}
		RedisDbExecute.returnResource(jedis);
		return result;
	}
	
	/**
	 * 获取设备品牌Text
	 * gislin
	 * 2016年4月25日
	 * @param pollCode
	 * @param attr
	 * @return
	 */
	public String getDeviceBandText(String mn,String deviceCode){
		String bandCode = getDeviceBandCode(mn, deviceCode);
		String value = translationDictValue("检测仪器品牌", bandCode);
		return value;
	}
	
	/**
	 * 获取设备状态文本
	 * gislin
	 * 2016年4月25日
	 * @param pollCode
	 * @param attr
	 * @return
	 */
	public String getDeviceStatusText(String mn,String deviceCode){
		String key = "stationInfo:"+mn+":deviceInfo:"+deviceCode+"_STATUS";
		String value = RedisDbExecute.getString(key);
		if(value == null){
			return "";
		}
		value = value.replace(".0", "");
		String bandCode = getDeviceBandCode(mn, deviceCode);
		String text = translationDeviceStatus(deviceCode, bandCode,"STATUS",value);
		return text;
	}
	
	/**
	 * 获取设备进程文本
	 * gislin
	 * 2016年4月25日
	 * @param pollCode
	 * @param attr
	 * @return
	 */
	public String getDeviceProcessText(String mn,String deviceCode){
		String key = "stationInfo:"+mn+":deviceInfo:"+deviceCode+"_PROCESS";
		String value = RedisDbExecute.getString(key);
		if(value == null){
			return "";
		}
		value = value.replace(".0", "");
		String bandCode = getDeviceBandCode(mn, deviceCode);
		String text = translationDeviceStatus(deviceCode, bandCode,"PROCESS",value);
		return text;
	}
	
	/**
	 * 获取设备错误文本
	 * gislin
	 * 2016年4月25日
	 * @param pollCode
	 * @param attr
	 * @return
	 */
	public String getDeviceErrorText(String mn,String deviceCode){
		String key = "stationInfo:"+mn+":deviceInfo:"+deviceCode+"_ERROR";
		String value = RedisDbExecute.getString(key);
		if(value == null){
			return "";
		}
		value = value.replace(".0", "");
		String bandCode = getDeviceBandCode(mn, deviceCode);
		String text = translationDeviceStatus(deviceCode, bandCode,"ERROR",value);
		return text;
	}
	
	/**
	 * 获取站房信息，温度湿度等
	 * gislin
	 * 2016年1月5日
	 * @param mn
	 * @return
	 */
	public List<RowBase> getStationHouseData(String mn){
		
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		SimpleDateFormat dateParse = new SimpleDateFormat("yyyyMMddHHmmss");
		
		String keyPrix = "stationInfo:"+mn+":sysStatus:";
		Set<String> keySet = RedisDbExecute.queryKeys(keyPrix+"*");
		
		List<RowBase> mnInfoList = new ArrayList<>();
		RowBase row = new RowBase();		
		mnInfoList.add(row);
		
		for(String key : keySet){
			String value = RedisDbExecute.getString(key);
			String oldValue = value.replace(".0", "");
			String simpleKeyName = key.replace(keyPrix, "");
			
			if(simpleKeyName.indexOf("SYS_MODEL") > -1 ||
					simpleKeyName.indexOf("SYS_PROCESS") > -1 ||
					simpleKeyName.indexOf("SYS_MEAS_MODEL") > -1 ||
					simpleKeyName.indexOf("SYS_ERROR") > -1 ||
					simpleKeyName.indexOf("door") > -1 ||
					simpleKeyName.indexOf("power") > -1){
				value = value.replace(".0", "");
				value = translationSysStatus(simpleKeyName, value);
			}
			else if(simpleKeyName.indexOf("TIME") > -1){
				try {
					value = dateFormat.format(dateParse.parse(value));
				} catch (Exception e) {
					
				}
			}
			row.setValue(simpleKeyName, value);
			row.setValue(simpleKeyName+"_OLD", oldValue);
		}
		
		//数据时间
		String dataTimeKey = "stationInfo:"+mn+":deviceInfo:DataTime_s";
		String dataTimeValue = RedisDbExecute.getString(dataTimeKey);
		try {
			String dataTimeValueStr = dataTimeValue;
			row.setValue("DataTime", dataTimeValueStr);
		} catch (Exception e) {
			
		}
		
		return mnInfoList;
	}
	
	/**
	 * 获取某个参数的质控配置
	 * gislin
	 * 2016年4月21日
	 * @param mn
	 * @param pollName
	 * @return
	 */
	public HashMap<String, String> getQualityConfig(String mn,String pollName){
		Set<String> keys = RedisDbExecute.queryKeys("stationInfo:"+mn+":qualityConfig:"+pollName+"*");
		keys.add("stationInfo:"+mn+":qualityConfig:YB_CBJM_Cycle");
		keys.add("stationInfo:"+mn+":qualityConfig:YB_CBJM_Number");
		
		HashMap<String, String> result = new HashMap<>();
		
		for(String key:keys){
			String value = RedisDbExecute.getString(key);
			key = key.replace("stationInfo:"+mn+":qualityConfig:", "");
			result.put(key, value);
		}
		
		return result;
	}
	
	/**
	 * 翻译设备的状态码
	 * gislin
	 * 2016年3月17日
	 * @return
	 */
	private String translationDeviceStatus(String deviceCode,String band,String attrName,String code){
		
		String hasKey = RedisDbExecute.getString("statusDict:hasKey");
		
		if(hasKey == null || hasKey.trim().equals("")){
			initStatusMap();
		}
		
		String resultValue = "";
		
		// 是否按位读取
		String isBit = RedisDbExecute.getString("statusDict:deviceInfo:"+deviceCode+":"+band+":"+attrName+":bit");
		
		if(isBit != null && !isBit.trim().equals("")){
			BigDecimal db = new BigDecimal(code);
			String bitStr = Long.toString(db.longValue(), 2);

			for(int i=0;i<bitStr.length();i++){
				char c = bitStr.charAt(i);
				if(c == '1'){
					String key = "statusDict:deviceInfo:"+deviceCode+":"+band+":"+attrName+":"+i;
					String temValue = RedisDbExecute.getString(key);
					if(temValue == null){
						// 如果无对应翻译，则查找该品牌该状态的通用翻译
						key = "statusDict:deviceInfo:DEFAULT:"+band+":"+attrName+":"+i;
						temValue = RedisDbExecute.getString(key);
					}
					// 如果害找不到反应，则直接把状态码作为结果
					if(temValue == null){
						resultValue += ","+i;
					}
					else{
						resultValue += temValue+",";
					}
				}
			}
		}
		else{
			String key = "statusDict:deviceInfo:"+deviceCode+":"+band+":"+attrName+":"+code;
			resultValue += RedisDbExecute.getString(key);
			if(resultValue == null || resultValue.equals("") || resultValue.equals("null")){
				key = "statusDict:deviceInfo:DEFAULT:"+band+":"+attrName+":"+code;
				resultValue = RedisDbExecute.getString(key);
			}
		}
		
		//如果没有对应的反应，则查找是否有默认值，如果默认值还没有，就直接把状态码返回
		if(resultValue == null || resultValue.equals("") || resultValue.equals("null")){
			String key = "statusDict:deviceInfo:DEFAULT:DEFAULT:"+attrName+":"+code;
			resultValue = RedisDbExecute.getString(key);
			if(resultValue == null){
				resultValue = code;
			}
			else{
				resultValue +="("+code+")";
			}
		}
		
		resultValue = resultValue.replace("$,", "");
		
		return resultValue;
	}
	
	/**
	 * 把opc字典值映射到redis中去
	 * gislin
	 * 2016年3月18日
	 */
	private void initStatusMap(){
		
		String sql = " SELECT * FROM OPC_DICT ";
		List<RowBase> datas = DataUtil.getSelectRows(sql,null);
		
		for(RowBase row : datas){
			String band = row.getSafeString("BAND");
			String value = row.getSafeString("VALUE");
			String code = row.getSafeString("CODE");
			String parmName = row.getSafeString("PARM_NAME");
			String readByBit = row.getSafeString("READ_BIT");
			String attrName = row.getSafeString("ATTR_NAME");
			
			if(parmName != null && !parmName.equals("")){
				RedisDbExecute.setString("statusDict:deviceInfo:"+parmName+":"+band+":"+attrName+":"+code, value);
				if(readByBit != null && !readByBit.trim().equals("")){
					RedisDbExecute.setString("statusDict:deviceInfo:"+parmName+":"+band+":"+attrName+":bit", "1");
				}
			}
			else{
				RedisDbExecute.setString("statusDict:sysStatus:"+attrName+":"+code, value);
				if(readByBit != null && !readByBit.trim().equals("")){
					RedisDbExecute.setString("statusDict:sysStatus:"+attrName+":bit", "1");
				}
			}
		}
		RedisDbExecute.setString("statusDict:hasKey", "1");
	}
	
	/**
	 * 初始化站点名称字典
	 * gislin
	 * 2016年5月7日
	 */
	public void initStationNameMap(){
		String sql = "SELECT ms.NAME,dc.device_num,ms.code,station_category,t.name company_Name from BC_SITE_INFO MS\n" +
						"       inner JOIN BC_COLLECTION_INFO DC ON DC.Site_Id = ms.code\n"+
						" 		left join BC_ENTERPRISE_ATTR t on t.code = ms.wwtp_id ";
		
		try {
			DataTable table = DbManager.getInstance().getOracleExecuter().executeQuery(sql);
			for(int i=0;i<table.getRecordCount();i++){
				
				String mn = table.getString(i, "DEVICE_NUM");
				String stationName = table.getString(i, "NAME");
				String companyName = table.getString(i, "COMPANY_NAME");
				String stationCode = table.getString(i, "CODE");
				String stationCategory = table.getString(i, "STATION_CATEGORY");
				
				RedisDbExecute.setString("sysDict:stationNameDict:"+mn+":stationName", stationName);
				RedisDbExecute.setString("sysDict:stationNameDict:"+mn+":companyName", companyName);
				RedisDbExecute.setString("sysDict:stationNameDict:"+mn+":stationCode", stationCode);
				RedisDbExecute.setString("sysDict:stationNameDict:"+mn+":stationCategory", stationCategory);
				RedisDbExecute.setString("sysDict:stationNameDict:stationCode:"+stationCode+":deviceNum",mn);
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		RedisDbExecute.setString("sysDict:stationNameDict:hasKey", "1");
	}
	
	/**
	 * 初始化站点污染物报警阀值信息
	 * gislin
	 * 2016年5月13日
	 */
	public void initStationPollAlarm(){
		long startTime=System.currentTimeMillis();   //获取开始时间
		long endTime = System.currentTimeMillis(); //获取结束时间
		
		Jedis jedis = RedisDbExecute.getStationStatusDB();
		
		try {
			String sql = "select sp.name pollcode,"
					+"	t.density_alarm_dowmlimit down,"
				    +"   t.density_alarm_uplimit up,"
					+ "dc.device_num mn,"
					+ "ABNORMAL_ALARM_DOWN,"
					+ "ABNORMAL_ALARM_UP "
					+ "from BC_SITE_POLL sp\n" +
							"       left join BC_SITE_INFO ms on sp.site_id = ms.code\n" + 
							"       left join BC_COLLECTION_INFO dc on dc.site_id = ms.code"+
							"  left join BC_POLL_THRESHOLD t on t.SITE_POLLUTANTS_ID = sp.guid and t.is_standard = '1'"
							+ " where 1=1 ";

			List<RowBase> datas = DataUtil.getSelectRows(sql, null);
			
			endTime = System.currentTimeMillis();
			System.out.println("【initStationPollAlarm】获取阈值信息耗时： "+(endTime-startTime)+"ms");
			
			Pipeline pipeLine = jedis.pipelined();

			for(RowBase row:datas){
				
				String pollCode = row.getSafeString("POLLCODE");
				String down = row.getSafeString("DOWN");
				String up = row.getSafeString("UP");
				String mn = row.getSafeString("MN");
				String abnormalDown = row.getSafeString("ABNORMAL_ALARM_DOWN");
				String abnormalUp = row.getSafeString("ABNORMAL_ALARM_UP");
				
				RedisDbExecute.setString("sysDict:stationPollAlarm:"+mn+":"+pollCode+":down",down,pipeLine);
				RedisDbExecute.setString("sysDict:stationPollAlarm:"+mn+":"+pollCode+":up",up,pipeLine);
				
				RedisDbExecute.setString("sysDict:stationPollAlarm:"+mn+":"+pollCode+":abnormal_down",abnormalDown,pipeLine);
				RedisDbExecute.setString("sysDict:stationPollAlarm:"+mn+":"+pollCode+":abnormal_up",abnormalUp,pipeLine);
			}
			
			endTime = System.currentTimeMillis();
			System.out.println("【initStationPollAlarm】设置redis和ehcache耗时： "+(endTime-startTime)+"ms");
			
			RedisDbExecute.setString("sysDict:stationPollAlarm:hasKey","my",pipeLine);
			
			pipeLine.sync();
			
			endTime = System.currentTimeMillis();
			System.out.println("【initStationPollAlarm】提交redis数据耗时： "+(endTime-startTime)+"ms");
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			RedisDbExecute.returnResource(jedis);
		}
	}
	
	/**
	 * 翻译系统状态码
	 * gislin
	 * 2016年3月18日
	 * @param attrName
	 * @param code
	 * @return
	 */
	private String translationSysStatus(String attrName,String code){
		String hasKey = RedisDbExecute.getString("statusDict:hasKey");
		
		if(hasKey == null || hasKey.trim().equals("")){
			initStatusMap();
		}
		
		String isBit = RedisDbExecute.getString("statusDict:sysStatus:"+attrName+":bit");
		String resultValue = "";
		
		if(isBit != null && !isBit.trim().equals("")){
			BigDecimal db ;
			try {
				db = new BigDecimal(code);
			} catch (Exception e) {
				return "";
			}
			
			String bitStr = Long.toString(db.longValue(), 2);

			for(int i=0;i<bitStr.length();i++){
				char c = bitStr.charAt(i);
				if(c == '1'){
					String key = "statusDict:sysStatus:"+attrName+":"+i;
					String temValue = RedisDbExecute.getString(key);
					if(temValue == null){
						resultValue += ","+i;
					}
					else{
						resultValue += temValue+",";
					}
				}
			}
		}
		else{
			String key = "statusDict:sysStatus:"+attrName+":"+code;
			resultValue = RedisDbExecute.getString(key);
		}
		
		if(resultValue == null || resultValue.equals("") ){
			String key = "statusDict:sysStatus:"+attrName+":default";
			resultValue = RedisDbExecute.getString(key);
			if(resultValue == null){
				resultValue = code;
			}
			else{
				resultValue +="("+code+")";
			}
		}
		resultValue = resultValue.replace(",$", "");
		
		return resultValue;
	}
	
	/**
	 * 根据设备编号翻译站点名称
	 * gislin
	 * 2016年5月7日
	 * @param mn
	 * @return
	 */
	public String getStationNameByMN(String mn){
		String hasKey = RedisDbExecute.getString("sysDict:stationNameDict:hasKey");
		
		if(hasKey == null || hasKey.trim().equals("")){
			initStationNameMap();
		}
		
		String result = RedisDbExecute.getString("sysDict:stationNameDict:"+mn+":stationName");
		return result;
	}
	
	/**
	 * 根据设备编号翻译站点的上级单位名称
	 * @param mn
	 * @return
	 */
	public String getStationCompanyNameByMN(String mn){
		
		String hasKey = RedisDbExecute.getString("sysDict:stationNameDict:hasKey");
		
		if(hasKey == null || hasKey.trim().equals("")){
			initStationNameMap();
		}
		
		String result = RedisDbExecute.getString("sysDict:stationNameDict:"+mn+":companyName");
		return result;
	}
	
	/**
	 * 根据设备编号获取站点编号
	 * gislin
	 * 2016年5月9日
	 * @param mn
	 * @return
	 */
	public String getStationCodeByMN(String mn){
		String hasKey = RedisDbExecute.getString("sysDict:stationNameDict:hasKey");
		
		if(hasKey == null || hasKey.trim().equals("")){
			initStationNameMap();
		}
		
		String result = RedisDbExecute.getString("sysDict:stationNameDict:"+mn+":stationCode");
		return result;
	}
	
	/**
	 * 根据站点编号获取mn
	 * gislin
	 * 2016年8月17日
	 * @param stationCode
	 * @return
	 */
	public String getMNByStationCode(String stationCode){
		String hasKey = RedisDbExecute.getString("sysDict:stationNameDict:hasKey");
		
		if(hasKey == null || hasKey.trim().equals("")){
			initStationNameMap();
		}
		String result = RedisDbExecute.getString("sysDict:stationNameDict:stationCode:"+stationCode+":deviceNum");
		return result;
	}
	
	/**
	 * 获取站点类型
	 * gislin
	 * 2016年5月7日
	 * @param mn
	 * @return
	 */
	public String getStationTypeByMn(String mn){
		String hasKey = RedisDbExecute.getString("sysDict:stationNameDict:hasKey");
		
		if(hasKey == null || hasKey.trim().equals("")){
			initStationNameMap();
		}
		
		String result = RedisDbExecute.getString("sysDict:stationNameDict:"+mn+":stationCategory");
		return result;
	}
	
	/**
	 * 获取污染物的报警上限阀值
	 * gislin
	 * 2016年5月13日
	 * @return
	 */
	public Double getPollAlarmUp(String mn,String pollCode){
		Object hasKey = RedisEhcacheUtil.getInstance().get("sysDict:stationPollAlarm:hasKey");
		
		if(hasKey == null ){
			initStationPollAlarm();
		}
		Double up =  RedisEhcacheUtil.getInstance().getDouble("sysDict:stationPollAlarm:"+mn+":"+pollCode+":up");
		
		return up;
	}
	
	/**
	 * 获取污染物的报警下限阀值
	 * gislin
	 * 2016年5月13日
	 * @return
	 */
	public Double getPollAlarmDown(String mn,String pollCode){
		Object hasKey = RedisEhcacheUtil.getInstance().get("sysDict:stationPollAlarm:hasKey");
		
		if(hasKey == null){
			initStationPollAlarm();
		}
		Double down = RedisEhcacheUtil.getInstance().getDouble("sysDict:stationPollAlarm:"+mn+":"+pollCode+":down");
		
		return down;
	}
	
	/**
	 * 获取污染物异常报警下限
	 * gislin
	 * 2016年8月5日
	 * @param mn
	 * @param pollCode
	 * @return
	 */
	public Double getPollAbnormalDown(String mn,String pollCode){
		Object hasKey = RedisEhcacheUtil.getInstance().get("sysDict:stationPollAlarm:hasKey");
		
		if(hasKey == null ){
			initStationPollAlarm();
		}
		Double down = RedisEhcacheUtil.getInstance().getDouble("sysDict:stationPollAlarm:"+mn+":"+pollCode+":abnormal_down");
		
		return down;
	}
	
	/**
	 * 获取污染物异常报警上限
	 * gislin
	 * 2016年8月5日
	 * @param mn
	 * @param pollCode
	 * @return
	 */
	public Double getPollAbnormalUp(String mn,String pollCode){
		Object hasKey = RedisEhcacheUtil.getInstance().get("sysDict:stationPollAlarm:hasKey");
		
		if(hasKey == null ){
			initStationPollAlarm();
		}
		Double down = RedisEhcacheUtil.getInstance().getDouble("sysDict:stationPollAlarm:"+mn+":"+pollCode+":abnormal_up");
		
		return down;
	}
}
